package build_resource

import (
	"go_server/game_server/api/service/bag"
	"go_server/game_server/api/service/build"
	"go_server/game_server/constants"
	"go_server/game_server/dao"
	"go_server/game_server/dataconfig/config_manager"
	"go_server/game_server/event_manager"
	"go_server/game_server/event_manager/event_data/event_impl"
	"go_server/game_server/initializer/map_data_init"
	"go_server/game_server/protocol/pb"
	"go_server/game_server/util"
	"go_server/game_server/world_manager"
	"go_server/zinx/ziface"
	"go_server/zinx/zlog"
	"go_server/zinx/znet"
	"gorm.io/datatypes"
	"math"
	"time"
)

type BuildResourceCollectApi struct {
	znet.BaseRouter
}

// 资源采集
func (*BuildResourceCollectApi) Handle(request ziface.IRequest) {
	msg := &pb.BuildResourceCollectC2S{}
	if !util.PBParseRet(request, msg) {
		return
	}

	conn := request.GetConnection()
	roleId := ServiceObj.GetRoleId(request)

	if msg.Infos == nil || len(msg.Infos) <= 0 || msg.Ty < START_COLLECT_RESOURCE || msg.Ty > COLLECT_RESOURCE {
		world_manager.WorldMgrObj.SendClientErrMsg(roleId, request, pb.ErrorCodeManager_PARAM_ERROR, nil)
		return
	}

	row := dao.GetBuildRobotInfo(roleId)

	buildResourceData := make(map[int32]map[int32][]int64)
	buildStates := make(map[int32]int64)
	curTime := time.Now().UnixMilli() // 当前毫秒时间戳

	if row != nil && row.BuildResourceData.Data() != nil {
		buildResourceData = row.BuildResourceData.Data()
	}

	if len(buildResourceData) > 0 {
		for buildId, buildInfo := range buildResourceData {
			totalTime := int64(0) // 累计采集时间

			for _, robotInfo := range buildInfo {
				if robotInfo[0] == START_COLLECT_RESOURCE {
					totalTime += curTime - robotInfo[1]
				}

				// 历史之前累计采集时间，未被采集
				if robotInfo[2] > 0 {
					totalTime += robotInfo[2]
				}
			}
			buildStates[buildId] = totalTime
		}
	}

	res := new(pb.BuildResourceCollectS2C)
	resList := make(map[int32]*pb.BuildResourceCollectRes)

	switch msg.Ty {
	case START_COLLECT_RESOURCE: // 开始
		{
			for _, buildResourceCollectInfo := range msg.Infos {
				if buildResourceCollectInfo.BuildId <= 0 {
					world_manager.WorldMgrObj.SendClientErrMsg(roleId, request, pb.ErrorCodeManager_PARAM_ERROR, nil)
					return
				}

				eventSet := util.NewSet[int32]()
				eventSet.AddValue(cfgBuildIds)
				if !eventSet.Contains(buildResourceCollectInfo.BuildId) {
					world_manager.WorldMgrObj.SendClientErrMsg(roleId, request, pb.ErrorCodeManager_PARAM_ERROR, nil)
					return
				}

				if buildInfo, exist := buildResourceData[buildResourceCollectInfo.BuildId]; exist {
					if robotInfo, ok := buildInfo[buildResourceCollectInfo.RobotSerId]; ok {
						if robotInfo[0] == START_COLLECT_RESOURCE { // 如果当前机器人状态正在采集中,则不做任何处理
							continue
						}

						// 记录开始采集时间戳
						robotInfo[0] = START_COLLECT_RESOURCE
						robotInfo[1] = curTime
						buildResourceData[buildResourceCollectInfo.BuildId][buildResourceCollectInfo.RobotSerId] = robotInfo
					} else {
						buildResourceData[buildResourceCollectInfo.BuildId][buildResourceCollectInfo.RobotSerId] = []int64{START_COLLECT_RESOURCE, curTime, 0}
					}
				} else {
					buildInfo = make(map[int32][]int64)
					buildInfo[buildResourceCollectInfo.RobotSerId] = []int64{START_COLLECT_RESOURCE, curTime, 0} // [机器人状态,开始采集时间戳,累计采集时间]
					buildResourceData[buildResourceCollectInfo.BuildId] = buildInfo
				}

				totalCollectTime := int64(0) // 累计采集时间戳,毫秒单位
				if _, exist := buildStates[buildResourceCollectInfo.BuildId]; !exist {
					totalCollectTime = buildStates[buildResourceCollectInfo.BuildId]
				}

				resList[buildResourceCollectInfo.BuildId] = &pb.BuildResourceCollectRes{
					CurrencyId:       0,
					CollectNum:       0,
					TotalCollectTime: totalCollectTime,
				}
			}

			res.ResList = resList
			res.Ty = msg.Ty
			conn.SendBuffPBMsg(uint32(pb.ProtocolManager_BuildResourceCollect), res)

			// 更新机器人状态信息
			upData := map[string]any{
				"build_resource_data": datatypes.NewJSONType(buildResourceData),
			}
			dao.UpdateBuildRobotInfoByRoleId(roleId, &upData)
		}
	case STOP_COLLECT_RESOURCE: // 停止
		{
			for _, buildResourceCollectInfo := range msg.Infos {
				if buildResourceCollectInfo.BuildId <= 0 {
					world_manager.WorldMgrObj.SendClientErrMsg(roleId, request, pb.ErrorCodeManager_PARAM_ERROR, nil)
					return
				}

				eventSet := util.NewSet[int32]()
				eventSet.AddValue(cfgBuildIds)
				if !eventSet.Contains(buildResourceCollectInfo.BuildId) {
					world_manager.WorldMgrObj.SendClientErrMsg(roleId, request, pb.ErrorCodeManager_PARAM_ERROR, nil)
					return
				}

				if buildInfo, exist := buildResourceData[buildResourceCollectInfo.BuildId]; exist {
					if robotInfo, ok := buildInfo[buildResourceCollectInfo.RobotSerId]; ok {
						if robotInfo[0] != START_COLLECT_RESOURCE { // 如果当前机器人状态没有开始采集，则不做任何处理
							continue
						}

						// 记录开始采集时间戳
						robotInfo[0] = STOP_COLLECT_RESOURCE
						robotInfo[2] += curTime - robotInfo[1]
						buildResourceData[buildResourceCollectInfo.BuildId][buildResourceCollectInfo.RobotSerId] = robotInfo
					} else {
						buildResourceData[buildResourceCollectInfo.BuildId][buildResourceCollectInfo.RobotSerId] = []int64{STOP_COLLECT_RESOURCE, 0, 0}
					}
				} else {
					buildInfo = make(map[int32][]int64)
					buildInfo[buildResourceCollectInfo.RobotSerId] = []int64{STOP_COLLECT_RESOURCE, 0, 0} // [机器人状态,开始采集时间戳,累计采集时间]
					buildResourceData[buildResourceCollectInfo.BuildId] = buildInfo
				}

				totalCollectTime := int64(0) // 累计采集时间戳,毫秒单位
				if _, exist := buildStates[buildResourceCollectInfo.BuildId]; exist {
					totalCollectTime = buildStates[buildResourceCollectInfo.BuildId]
				}

				resList[buildResourceCollectInfo.BuildId] = &pb.BuildResourceCollectRes{
					CurrencyId:       0,
					CollectNum:       0,
					TotalCollectTime: totalCollectTime,
				}
			}

			res.ResList = resList
			res.Ty = msg.Ty
			conn.SendBuffPBMsg(uint32(pb.ProtocolManager_BuildResourceCollect), res)

			// 更新机器人状态信息
			upData := map[string]any{
				"build_resource_data": datatypes.NewJSONType(buildResourceData),
			}
			dao.UpdateBuildRobotInfoByRoleId(roleId, &upData)
		}
	case COLLECT_RESOURCE: // 采集
		{
			// 更客户端协商确定，采集单次只会请求一个建筑

			buildId := msg.Infos[0].BuildId

			if buildId <= 0 {
				world_manager.WorldMgrObj.SendClientErrMsg(roleId, request, pb.ErrorCodeManager_PARAM_ERROR, nil)
				return
			}

			eventSet := util.NewSet[int32]()
			eventSet.AddValue(cfgBuildIds)
			if !eventSet.Contains(buildId) {
				world_manager.WorldMgrObj.SendClientErrMsg(roleId, request, pb.ErrorCodeManager_PARAM_ERROR, nil)
				return
			}

			buildLevel := build.GetBuildLv(roleId, map_data_init.InitMapID, buildId, constants.RESOURCE_BUILD_CFG_ID) // 获取当前资源建筑等级

			cfgBL := config_manager.GetTableBuildSheetLevelConfig(buildId, buildLevel)
			if &cfgBL == nil { // 当前资源建筑等级配置不存在
				world_manager.WorldMgrObj.SendClientErrMsg(roleId, request, pb.ErrorCodeManager_RESOURCE_BUILD_LEVEL_UNFIND, nil)
				return
			}

			var hour = float64(60 * 60 * 1000)                   // 一小时的时间戳,毫秒
			var produceNum = int64(cfgBL.Effect[0])              // 当前建筑等级每小时产出数
			var refreshCycleTime = int64(cfgBL.Effect[1]) * 1000 // 当前建筑等级资源采集刷新周期

			totalCollectTime := int64(0) // 累计采集时间戳,毫秒单位
			if _, exist := buildStates[buildId]; exist {
				totalCollectTime = buildStates[buildId]
			}

			zlog.Infof("totalCollectTime=%d,refreshCycleTime=%v", totalCollectTime, refreshCycleTime)

			if totalCollectTime < refreshCycleTime { // 当前累计采集时间戳 小于采集周期时间,不能采集
				world_manager.WorldMgrObj.SendClientErrMsg(roleId, request, pb.ErrorCodeManager_CANT_COLLECT_RESOURCE, nil)
				return
			}

			if buildInfo, ok := buildResourceData[buildId]; !ok { // 没有机器人采集信息，则不能采集
				world_manager.WorldMgrObj.SendClientErrMsg(roleId, request, pb.ErrorCodeManager_CANT_COLLECT_RESOURCE, nil)
				return
			} else {
				// 计算可以采集的资源数量，向上取整
				collectNum := int32(math.Ceil(float64(totalCollectTime*produceNum) / hour))

				// 读取货币配置
				currencyCfg := config_manager.GetTableCurrencySheetCurrencyBYBuildId(buildId)

				resList[buildId] = &pb.BuildResourceCollectRes{
					CurrencyId:       currencyCfg.Itemid,
					CollectNum:       collectNum,
					TotalCollectTime: 0, // 清零累计采集时间戳
				}

				res.ResList = resList
				res.Ty = msg.Ty

				zlog.Infof("totalTime=%d,res=%v", totalCollectTime, res)
				// 优先返回下行
				conn.SendBuffPBMsg(uint32(pb.ProtocolManager_BuildResourceCollect), res)

				// 更新机器人状态信息
				for robotId, robotInfo := range buildInfo {
					buildInfo[robotId] = []int64{robotInfo[0], curTime, 0} // 更新机器人状态
				}

				buildResourceData[buildId] = buildInfo

				defer func() {
					upData := map[string]any{
						"build_resource_data": datatypes.NewJSONType(buildResourceData),
					}
					dao.UpdateBuildRobotInfoByRoleId(roleId, &upData)
				}()

				// 发送资源
				if currencyCfg.Itemid > 0 && collectNum > 0 {
					bag.AddItemSingle(roleId, currencyCfg.Itemid, collectNum)

					// 创建资源采集事件
					event_manager.EventManagerObj.FireEventData(event_impl.NewBuildResourceCollectEvent(conn, map[string]int32{
						"id":    currencyCfg.Itemid,
						"value": collectNum,
					}))
				}
			}
		}
	}
}
